Sunday, July 24, 2016

LC349 Intersection of Two Arrays

Given two arrays, write a function to compute their intersection.
Example:
Given nums1 = [1, 2, 2, 1]nums2 = [2, 2], return [2].
Note:
  • Each element in the result must be unique.
  • The result can be in any order.
public class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> set = new HashSet<>();
        Set<Integer> intersect = new HashSet<>();
        for (int i = 0; i < nums1.length; i++) {
            set.add(nums1[i]);
        }
        for (int i = 0; i < nums2.length; i++) {
            if (set.contains(nums2[i])) {
                intersect.add(nums2[i]);
            }
        }
        int[] result = new int[intersect.size()];
        int i = 0;
        for (Integer num : intersect) {
            result[i++] = num;
        }
        return result;
    }
}

Wednesday, April 27, 2016

Array of Objects

As we have already said, arrays are capable of storing objects also. For example, we can create an array of Strings which is a reference type variable. However, using a String as a reference type to illustrate the concept of array of objects isn't too appropriate due to the immutability of String objects. Therefore, for this purpose, we will use a class Student containing a single instance variable marks. Following is the definition of this class.
class Student {
   int marks;
}
An array of objects is created just like an array of primitive type data items in the following way.
Student[] studentArray = new Student[7];
The above statement creates the array which can hold references to seven Student objects. It doesn't create the Student objects themselves. They have to be created separately using the constructor of the Student class. The studentArray contains seven memory spaces in which the address of seven Student objects may be stored. If we try to access the Student objects even before creating them, run time errors would occur. For instance, the following statement throws a NullPointerException during runtime which indicates that studentArray[0] isn't yet pointing to a Student object.
studentArray[0].marks = 100;

In this way, we create the other Student objects also. If each of the Student objects have to be created using a different constructor, we use a statement similar to the above several times. However, in this particular case, we may use a for loop since all Student objects are created with the same default constructor.
for ( int i=0; i<studentArray.length; i++) {
studentArray[i]=new Student();
}
The above for loop creates seven Student objects and assigns their reference to the array elements. Now, a statement like the following would be valid.
studentArray[0].marks=100;
Enhanced for loops find a better application here as we not only get the Student object but also we are capable of modifying it. This is because of the fact that Student is a reference type. Therefore the variable in the header of the enhanced for loop would be storing a reference to the Student object and not a copy of the Student object which was the case when primitive type variables like int were used as array elements.
for ( Student x : studentArray ) {
    x.marks = s.nextInt(); // s is a Scanner object
}

If you know how to create one dimensional array and fact that multi-dimensional arrays are just array of array in Java, then creating a 2 dimensional array is very easy. Instead of one bracket, you will use two e.g. int[][] is a two dimensional integer array. You can define a 2D array in Java as follows :
int[][] multiples = new int[4][2];     // 2D integer array with 4 rows and 2 columns
String[][] cities = new String[3][3];  // 2D String array with 3 rows and 3 columns
By the way when you initially declare a two dimensional array, you must remember to specify first dimension, for example following array declaration is illegal in Java.
 int[][] wrong = new int[][]; // not OK, you must specify 1st dimension
 int[][] right = new int[2][]; // OK
The first expression will throw "Variable must provide either dimension expressions or an array initializer" error at compile time. On the other hand second dimension is optional and even if you don't specify compiler will not complain, as shown below :
String[][] myArray = new String[5][]; // OK
String[][] yourArray = new String[5][4]; // OK


Read more: http://java67.blogspot.com/2014/10/how-to-create-and-initialize-two-dimensional-array-java-example.html#ixzz474GE4v00

Thursday, March 24, 2016

const C/C++ Keyword

const在C语言中算是一个比较新的描述符,我们称之为常量修饰符,即就是说其所修饰的对象为常量。当你代码中想要设法阻止一个变量被改变,那么这个时候可以选择使用const关键字。在你给一个变量加上const修饰符的同时,通常需要对它进行初始化,在之后的程序中就不能再去改变它。
可能有的人会有一个疑问,我们不是有在C中有预处理指令#define VariableName VariableValue 可以很方便地进行值替代,干嘛还要引入const修饰符呢?!这是因为预处理语句虽然可以很方便的进行值得替代,但它有个比较致命的缺点,即预处理语句仅仅只是简单值替代,缺乏类型的检测机制。这样预处理语句就不能享受C编译器严格类型检查的好处,正是由于这样,使得它的使用存在着一系列的隐患和局限性。

from geeksforgeeks

1) Normal Pointer
#include <stdio.h>
int main(void)
{
    int i = 10;
    int j = 20;
    int *ptr = &i;        /* pointer to integer */
    printf("*ptr: %d\n", *ptr);
  
    /* pointer is pointing to another variable */
    ptr = &j;
    printf("*ptr: %d\n", *ptr);
  
    /* we can change value stored by pointer */
    *ptr = 100;
    printf("*ptr: %d\n", *ptr);
  
    return 0;
}

Output:
    *ptr: 10
    *ptr: 20
    *ptr: 100

2) Pointer to constant
const int *ptr;
or int const *ptr;

#include <stdio.h>
int main(void)
{
    int i = 10;  
    int j = 20;
    const int *ptr = &i;    /* ptr is pointer to constant */
  
    printf("ptr: %d\n", *ptr);
    *ptr = 100;        /* error: object pointed cannot be modified
                     using the pointer ptr */
  
    ptr = &j;          /* valid */
    printf("ptr: %d\n", *ptr);
  
    return 0;
}


Output:
 error: assignment of read-only location ‘*ptr’

#include <stdio.h>
int main(void)
    int const i = 10;    /* i is stored in read only area*/
    int j = 20;
    int const *ptr = &i;        /* pointer to integer constant. Here i
                                 is of type "const int", and &i is of
                                 type "const int *".  And p is of type                           
                                "const int", types are matching no issue */
    printf("ptr: %d\n", *ptr);
    *ptr = 100;        /* error */
    ptr = &j;          /* valid. We call it as up qualification. In
                         C/C++, the type of "int *" is allowed to up
                         qualify to the type "const int *". The type of
                         &j is "int *" and is implicitly up qualified by
                         the compiler to "cons tint *" */
    printf("ptr: %d\n", *ptr);
    return 0;
}

Output:
 error: assignment of read-only location ‘*ptr’


#include <stdio.h>
int main(void)
{
    int i = 10;
    int const j = 20;
    /* ptr is pointing an integer object */
    int *ptr = &i;
    printf("*ptr: %d\n", *ptr);
    /* The below assignment is invalid in C++, results in error
       In C, the compiler *may* throw a warning, but casting is
       implicitly allowed */
    ptr = &j;
    /* In C++, it is called 'down qualification'. The type of expression
       &j is "const int *" and the type of ptr is "int *". The
       assignment "ptr = &j" causes to implicitly remove const-ness
       from the expression &j. C++ being more type restrictive, will not
       allow implicit down qualification. However, C++ allows implicit
       up qualification. The reason being, const qualified identifiers
       are bound to be placed in read-only memory (but not always). If
       C++ allows above kind of assignment (ptr = &j), we can use 'ptr'
       to modify value of j which is in read-only memory. The
       consequences are implementation dependent, the program may fail
       at runtime. So strict type checking helps clean code. */
    printf("*ptr: %d\n", *ptr);
    return 0;
}

3) Constant pointer to variable.
#include <stdio.h>
  
int main(void)
{
   int i = 10;
   int j = 20;
   int *const ptr = &i;    /* constant pointer to integer */
  
   printf("ptr: %d\n", *ptr);
  
   *ptr = 100;    /* valid */
   printf("ptr: %d\n", *ptr);
  
   ptr = &j;        /* error */
   return 0;
}


Output:
 error: assignment of read-only variable ‘ptr’


A. const char *pContent;
B. char * const pContent;
C. char const *pContent;
D. const char* const pContent;

对于前三种写法,我们可以换个方式,给其加上括号
A. const (char) *pContent;
B. (char*) const pContent;
C. (char) const *pContent;
这样就一目了然。根据对于const修饰非指针变量的规则,很明显,A=C.

对于A,C, const修饰的类型为char的变量*pContent为常量,因此,pContent的内容为常量不可变.
对于B, 其实还有一种写法: const (char*) pContent;
含义为:const修饰的类型为char*的变量pContent为常量,因此,pContent指针本身为常量不可变.
对于D, 其实是AB的混合体,表示指针本身和指针内容两者皆为常量不可变

总结:
(1)  指针本身是常量不可变
(char*) const pContent;
const (char*) pContent;

(2)  指针所指向的内容是常量不可变
const (char) *pContent;
(char) const *pContent;

(3)  两者都不可变
const char* const pContent;



  • const限定符和static的区别

      1. const定义的常量在超出其作用域之后其空间会被释放,而static定义的静态常量在函数执行后不会释放其存储空间。
      2. static表示的是静态的。类的静态成员函数、静态成员变量是和类相关的,而不是和类的具体对象相关的。即使没有具体对象,也能调用类的静态成员函数和成员变量。一般类的静态函数几乎就是一个全局函数,只不过它的作用域限于包含它的文件中。
      3. 在C++中,static静态成员变量不能在类的内部初始化。在类的内部只是声明,定义必须在类定义体的外部,通常在类的实现文件中初始化,如:double Account::Rate=2.25; static关键字只能用于类定义体内部的声明中,定义时不能标示为static
      4. 在C++中,const成员变量也不能在类定义处初始化,只能通过构造函数初始化列表进行,并且必须有构造函数。
      5. const数据成员,只在某个对象生存期内是常量,而对于整个类而言却是可变的。因为类可以创建多个对象,不同的对象其const数据成员的值可以不同。所以不能在类的声明中初始化const数据成员,因为类的对象没被创建时,编译器不知道const数据成员的值是什么。
      6. const数据成员的初始化只能在类的构造函数的初始化列表中进行。要想建立在整个类中都恒定的常量,应该用类中的枚举常量来实现,或者static const。
      7. const成员函数主要目的是防止成员函数修改对象的内容。即const成员函数不能修改成员变量的值,但可以访问成员变量。当方法成员函数时,该函数只能是const成员函数。
      8. static成员函数主要目的是作为类作用域的全局函数。不能访问类的非静态数据成员。类的静态成员函数没有this指针,这导致:1、不能直接存取类的非静态成员变量,调用非静态成员函数2、不能被声明为virtual 
      其中关于static、const、static cosnt、const static成员的初始化问题:
      • 类里的const成员初始化
           在一个类里建立一个const时,不能给他初值
      • 类里的static成员初始化:
            类中的static变量是属于类的,不属于某个对象,它在整个程序的运行过程中只有一个副本,因此不能在定义对象时 对变量进行初始化,就是不能用构造函数进行初始化,其正确的初始化方法是:
      数据类型 类名::静态数据成员名=值